springcloud gateway配置RedisRateLimiter限流无效但无报错信息,redis中无限流key |
您所在的位置:网站首页 › springcloud gateway限流配置 › springcloud gateway配置RedisRateLimiter限流无效但无报错信息,redis中无限流key |
最近在学习springcloud gateway在学习限流时配置使用的RedisRateLimiter配置了限流,但是redis中无法存入key并且限流无效,但是后台却无报错信息,我使用的是springcloud版本是2.1.1.RELEASE springcloud gateway限流教程 https://blog.csdn.net/forezp/article/details/85081162 分析源码控制限流的代码主要在RedisRateLimiter中的isAllowed方法 @Override @SuppressWarnings("unchecked") //根据keyresolver对request生成1个routeId,然后对该routeId采取其对应的限流 public Mono isAllowed(String routeId, String id) { if (!this.initialized.get()) { throw new IllegalStateException("RedisRateLimiter is not initialized"); } Config routeConfig = loadConfiguration(routeId); // How many requests per second do you want a user to be allowed to do?1秒多少个请求 int replenishRate = routeConfig.getReplenishRate(); // How much bursting do you want to allow?令牌桶的总容量 int burstCapacity = routeConfig.getBurstCapacity(); try { //redis中存有上次请求的时间,上次桶中剩下的令牌数两个key List keys = getKeys(id); // The arguments to the LUA script. time() returns unixtime in seconds. //执行脚本request_rate_limiter.lua(在gateway-core包中),请求中有四个参数 生成令牌速率,桶容量,当前时间,请求令牌数 List scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", Instant.now().getEpochSecond() + "", "1"); // allowed, tokens_left = redis.eval(SCRIPT, keys, args) Flux flux = this.redisTemplate.execute(this.script, keys, scriptArgs); // .log("redisratelimiter", Level.FINER); return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L))) .reduce(new ArrayList(), (longs, l) -> { longs.addAll(l); return longs; }).map(results -> { boolean allowed = results.get(0) == 1L; Long tokensLeft = results.get(1); Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft)); if (log.isDebugEnabled()) { log.debug("response: " + response); } return response; }); } catch (Exception e) { /* * We don't want a hard dependency on Redis to allow traffic. Make sure to set * an alert so you know if this is happening too much. Stripe's observed * failure rate is 0.01%. */ log.error("Error determining if user allowed from redis", e); } return Mono.just(new Response(true, getHeaders(routeConfig, -1L))); }主要问题就是在蓝色代码这一段在flux发生异常时,他的异常处理是直接使用flux([1,-1])这样一个数组进行后续操作,居然没有异常日志输出,导致一直请求redis失败,但是无异常日志,并且throwable -> Flux.just(Arrays.asList(1L, -1L)是在行内完成,无法直接定位异常信息,只能一层层往下找,在execute中有个eval方法 protected Flux eval(ReactiveRedisConnection connection, RedisScript script, ReturnType returnType, int numKeys, ByteBuffer[] keysAndArgs, RedisElementReader resultReader) { Flux result = connection.scriptingCommands().evalSha(script.getSha1(), returnType, numKeys, keysAndArgs); result = result.onErrorResume(e -> { if (ScriptUtils.exceptionContainsNoScriptError(e)) { return connection.scriptingCommands().eval(scriptBytes(script), returnType, numKeys, keysAndArgs); } return Flux .error(e instanceof RuntimeException ? (RuntimeException) e : new RedisSystemException(e.getMessage(), e)); }); return script.returnsRawValue() ? result : deserializeResult(resultReader, result); }将断点打在蓝色代码处终于定位到异常信息 org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'EVALSHA' 意思是redis不支持evalsha命令,估计是redis版本过低,不支持此命令,然后在虚拟机上重装了最新的5.0.5版本redis开墙等操作后,限流终于生效 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |